//// import { attributeDetail } from 'components/Attribute/modals/AttributeDetail';
//// import { wizardAttributeDetail } from 'components/Attribute/modals/WizardAttributeDetail';
import { treeForEach } from 'src/util/common';
import { debounce } from 'lodash';
import { GraphNodeType } from '@/constants/Enums';
import { ContextMenuUtil } from 'src/pages/mxgraph/ContextMenuUtil';
import siderBarJsonConfig from 'src/api/config/siderBarConfig';

import {
  sysml,
  SysMLUtilHelper
} from 'src/api/sysml-imports';
//// import treeContextMenuConfig from 'src/api/config/treeContextMenuConfig';
import menuItemPool from 'src/api/config/menuItemPool.json';
import { cloneDeep } from 'lodash';
import { GraphNodeStatus } from './../../constants/Enums';
import globalConfig from 'src/util/Global';

export default {
  //// attributeDetailVisible: false,
  //// wizardAttributeDetailVisible: false,
  dragData: undefined,
  setDragData(data){
    this.dragData = data;
  },
  getDragData(){
    return this.dragData;
  },

  //// 获取该typeName 或其子typeName下可容纳的diagram
  /**
   * 根据typeName获取创建图的菜单
   * @param typeName
   */
  getDiagramMenu(typeName:string){
    const typeNameConfig = app.activeProject.configManager.getTypeNameConfig();
    const nestConfig = app.activeProject.configManager.getNestConfig();
    const containTypes = nestConfig[typeName];
    const allItems = []; //// 所有能创建的图表
    console.log('typeName', typeName, containTypes, nestConfig);
    let menuList =  [
      {
        label: '最近使用',
        value: 'recent',
        children: []

      },
      {
        label: '基础图表',
        value: 'diagram',
        children: []
      },
      {
        label: '追溯图表',
        value: 'matrix',
        children: []
      },
      {
        label: '表格',
        value: 'table',
        children: []
      },
      { 
        label: '拓展', 
        value: 'diagram',
        children: []
      }
    ];
    const diagramTypes = [GraphNodeType.DIAGRAM, GraphNodeType.MATRIX, GraphNodeType.TABLE, GraphNodeType.RELATION_VIEW];
    //// 获取当前元素能创建的图表
    containTypes?.forEach(type1 => {
      const typeNameConfigItem = typeNameConfig[type1.typeName];
      if (diagramTypes.includes(typeNameConfigItem.type)){
        allItems.push({
          label: typeNameConfigItem.cnName,
          value: typeNameConfigItem.typeName,
          icon: typeNameConfigItem.icon,
          type: typeNameConfigItem.type
        });
      }

    });
    console.log('allItems', containTypes, [...allItems], typeNameConfig, nestConfig);

    //// 获得下级元素能创建的图表
    containTypes?.forEach(containdType => {
      const subItemNestItems = nestConfig[containdType.typeName];
      if (!subItemNestItems) return;
      subItemNestItems.forEach(t => {

        const subItemConfig = typeNameConfig[t.typeName];
        if (diagramTypes.includes(subItemConfig.type)){
          const existItem = allItems.find(i => i.value === subItemConfig.typeName);
          //// 如果不存在此类型的图表
          if (!existItem) {
            allItems.push({
              label: subItemConfig.cnName,
              value: subItemConfig.typeName,
              icon: subItemConfig.icon,
              createParentType: [containdType.typeName],
              type: subItemConfig.type
            });
            //// 如果已经存在，并且需要创建父元素
          } else if (existItem && existItem.createParentType) {
            existItem.createParentType.push(containdType.typeName);
          }
        }
      });
    });

    //// 将元素分类存储
    allItems?.forEach(item => {
      if (item.type === GraphNodeType.DIAGRAM) {
        if (item.value === 'RocketTD' || item.value === 'SysMLProfileDiagram'){
          menuList[4].children.push(item);
        } else {
          menuList[1].children.push(item);
        }
      } else  if (item.type === GraphNodeType.MATRIX || item.type === GraphNodeType.RELATION_VIEW) {
        menuList[2].children.push(item);
      } else  if (item.type === GraphNodeType.TABLE) {
        menuList[3].children.push(item);
      }
      if (app.ui.recentCreateDiagramTypes.includes(item.value)){
        menuList[0].children.push(item);
      }

    });
    menuList = menuList.filter(it => it.children.length > 0);
    console.log(menuList);
    return menuList;

  },
  /**
   * 获得树节点的右键菜单
   * @param graphNode
   * @param option
   */
  getMenuItems(graphNode:GraphNode, option = {}){
    //// console.log(model);

    const model = graphNode.model;
    const typeName = graphNode.getTypeName();
    if (!typeName) return [];

    if (app.activeProject.configManager === undefined) return false;
    const treeContextMenuConfig = app.activeProject.configManager.getTreeContextMenuConfig();
    const connectConfig = app.activeProject.configManager.getConnectConfig()[typeName];
    const menuKeys = treeContextMenuConfig[typeName];
    console.log('menuKeys', menuKeys);

    if (!menuKeys) return;
    const menus = cloneDeep( menuKeys.map(name => menuItemPool[name]));
    const menuItemMap:{[p:string]:TreeNode} = {};
    treeForEach(menus, (node:TreeNode) => {
      menuItemMap[node.value] = node;
      if (graphNode.status === GraphNodeStatus.FROM_PROFILE) { //// 处理导入的profile的menu选项
        if (node.value !== 'showAttribute' && node.value !== 'removeModel' && node.value !== 'navTo') {
          node.disabled = true;
        }
      }
    });

    //// disabled时禁用
    if (graphNode.disabled){
      menus.forEach(item => {
        if (item.disabledWhenReadonly) {
          item.disabled = true;
        }
      });
    }

    ////  复制粘贴的禁用
    console.log('menuItemMap', menuItemMap);

    //// menuItemMap.copyNode &&  (menuItemMap.copyNode.disabled = true);
    //// menuItemMap.pasteNode && (menuItemMap.pasteNode.disabled = true);
    const OutgoingMenu = menuItemMap.openCreateOutRelation;

    //// 关系的禁用
    if (OutgoingMenu && connectConfig){
      const list = connectConfig.outgoing;
      OutgoingMenu.disabled = !list || list.length === 0;
    }
    const IncomingMenu = menuItemMap.openCreateInRelation;
    if (IncomingMenu && connectConfig){
      const list =  connectConfig.incoming;
      IncomingMenu.disabled = !list || list.length === 0;

    }

    //// 导航
    const navTo = menuItemMap.navTo;
    if (navTo){
      navTo.children = ContextMenuUtil.getNavToMenu(graphNode);
    }

    //// 删除的禁用
    const removeModel = menuItemMap.removeModel;
    if (removeModel) {
      //// profile包可以删除
      if (graphNode.status === GraphNodeStatus.FROM_PROFILE) {
        if (!app.configManager.isNativeSt(graphNode.model)){
          menuItemMap.removeModel.disabled = false;
        }
      }
      if (app.configManager.getNotAllowDeleteTypes().includes(typeName)){
        removeModel.disabled = true;
      }
      //// 根节点不能删除
      if ( graphNode.getTypeName() === 'Model' && graphNode.container == null){
        removeModel.disabled = true;
      }
    }
    //// 导入导出的禁用，根节点不能导入导出
    //// const importMenu = menuItemMap.import;
    //// if (importMenu){
    ////   if (!graphNode.container){ //// 没有container是根节点
    ////     importMenu.disabled = true;
    ////   }else { //// 如果不是根节点

    ////   }
    //// }
    
    //// //// 根节点不能导出
    //// const exportMenu = menuItemMap.export;
    //// if (exportMenu){
    ////   if (!graphNode.container){
    ////     exportMenu.disabled = true;
    ////   }
    //// }
    //// 只有profile可以导出md3p
    const exportMd3p = menuItemMap.exportMd3p;
    if (exportMd3p){
      if (graphNode.getTypeName() !== 'Profile'){
        const index = menuItemMap.export.children.indexOf(exportMd3p);
        menuItemMap.export.children.splice(index, 1);
        //// exportMd3p.disabled = true;
      }
    }
    //// 未登录不能同步需求
    if (!globalConfig.token){
      const index = menus.findIndex(it => it.value === 'syncReq');
      if (index > -1){
        menus.splice(index, 1);
      }
    }
    //// 检入检出禁用
    //// 协同项目
    if ((!app.activeProject.config.online) || (graphNode.getTypeName() === 'Profile' && graphNode.status === GraphNodeStatus.FROM_PROFILE)){
      const index = menus.findIndex(it => it.value === 'cooperation');
      if (index > -1){
        menus.splice(index, 1);
      }
    } else if ( menuItemMap.cooperation) {
      menuItemMap.cooperation.disabled = false;
      const checkIn = menuItemMap.checkIn;
      const checkOut = menuItemMap.checkOut;
      const token = globalConfig.token;
      if (checkIn && [0, 1, 2].includes(graphNode.status)){
        checkIn.disabled = true;
      }
      if (checkOut && [0, 2, 3, 4].includes(graphNode.status)){
        checkOut.disabled = true;
      }
      if ( !token ){
        checkIn.disabled = true;
        checkOut.disabled = true;
      }
      //// if ( app.selectedElement.getParentNode().getTypeName() === 'Profile' ){
      ////   checkIn.disabled = true;
      ////   checkOut.disabled = true;
      //// }
      const importProjectMenu = menuItemMap.importProject;
      importProjectMenu && (importProjectMenu.disabled = true);
    }

    const renameMenu = menuItemMap.setNodeInEdit;
    if (renameMenu) {
      const propConfig = app.activeProject.configManager.getModelPropertyConfig()[typeName];
      if (!propConfig || !propConfig.properties.find(it => it.key === 'Name' || it.key === 'Body')){ //// 如果没有Name属性也没有Body属性则不能重命名 (Comment修改的是body属性)
        renameMenu.disabled = true;
      }
    }
    //// 仿真

    //// debugger;
    //// Reflect.deleteProperty(menuItemMap, 'openSimulateByContext');
    //// 添加、移除断点
    const addBP =  menuItemMap.setBreakPoint;
    const removeBP =  menuItemMap.removeBreakpoint;
    //// 当前设置只有活动图时可以打开仿真面板
    ;
    this.disableSim(menuItemMap, model, graphNode);
   
    //// 添加断点后“添加断点”置灰
    //// 删除断点后“删除断点”置灰
    if (addBP && removeBP){
      if (app.ui.breakpoints.has(model.getId())){
        addBP.disabled = true;
      } else {
        removeBP.disabled = true;
      }
    }

    return menus;
  
  },
  /**
     * 支持仿真的元素
        元素	说明
        block 及其 instanceSpecification 

        行为元素及其相应图表, 以及其instanceSpecification	
        activity，Activity Diagram

        statemachine, Statemachine Diagram 

        interaction, Sequence Diagram

        ibd, par 图	对ibd和par的仿真，实际上相当于对其block的仿真

        1，如果一个InstanceSpecification的classifier属性为空，那么其右键菜单中为 ：

        - 仿真 - 运行

        运行为禁用状态。

        2，如果其classifier有值，那么其右键菜单中仿真菜单的内容根据其classifier的第一个值来判断：

        若为block，则为 运行
        若为behavior且无context属性，则为 运行
        若为behavior且有context属性，则为 运行  /  上下文运行 
     */
  disableSim(menuItemMap, model, graphNode){
    const openSimPanel =  menuItemMap.openSimulate;
    const openSimulateByContext = menuItemMap.openSimulateByContext;
    const BehaviorList =  ["Block", "StateMachine",  "ConstraintBlock", 'Interaction', 'Activity' ];
    if (!openSimPanel) return;
    let ownerModel = model;
    if ( graphNode.getType() === 'diagram' && BehaviorList.includes(graphNode.container.model.getTypeName())){
      openSimulateByContext.disabled = false;
      return;
    }
    if ( SysMLUtilHelper.isInstanceSpecification(ownerModel) ){
      
      let InstanceSpecification =   ownerModel.classifiers?.toArray()[0];
      if ( InstanceSpecification && (BehaviorList.includes(InstanceSpecification.getTypeName())) ){
        openSimPanel.disabled = false;
        if ( typeof InstanceSpecification.context === 'function' && InstanceSpecification.context()){
          openSimulateByContext.disabled = false;
        }
        return; 
      }
    }
    if ((BehaviorList.includes(ownerModel.getTypeName())) ){
      openSimPanel.disabled = false;
      return; 
    }
   
  },

  updateGraphNodeChildren(graphNode, recursive){
    graphNode.children = graphNode.getChildren() || [];

  },
  updateChildrenDebounce: debounce(function(graphNode, recursive){
    //// this.updateGraphNodeChildren(graphNode, recursive);

  }, 20),

  getExistingRelation(filterCondition) {
    //// todo dependencyCriteria 同样需要过滤
    //// 这里的关系可以存在其他层，需要递归
    //// 这是个稀疏矩阵 可以直接统计 然后叠加到scope里面
    let existingRelationMatrix = {};
    let legend = {};
    let stats = { emptyRow: [], emptyCol: [], withRelationIds: { row: [], col: [] } };
    let relationResursive = relationGroup => {
      if (this.isProfile(relationGroup)) return;
      relationGroup.children.forEach(x => {
        if (this.isProfile(x)) return;
        if (x['getSourceConnector'] != undefined) {
          let stereotype = x.getTypeName();
          //// 过滤
          if (filterCondition.dependencyCriteria.filter(x => x.isVisible).map(x => x.icon).includes(stereotype)){
            legend[stereotype] = true;
            let targets = x.getSourceConnector();
            let sources = x.getTargetConnector();
            if (targets && sources) {
              let target = targets.graphElement;
              let source = sources.graphElement;
              if (target && source) {
              //// 是否有可能有多个元素??
              //// console.log(target.id, source.id, x, 'getExistingRelation');
                let key = target.id + '__' + source.id;

                if (stats.withRelationIds.row.filter(x => x.id == source.id).length === 0){
                  stats.withRelationIds.row.push(source);
                } else {
                  //// console.log('重复id');
                }
                if ( stats.withRelationIds.col.filter(x => x.id == target.id).length === 0){
                  stats.withRelationIds.col.push(target);
                } else {
                  //// console.log('重复id');
                }

                if (stats.withRelationIds.row.filter(x => x.id == target.id).length === 0){
                  stats.withRelationIds.row.push(target);
                } else {
                  console.log('重复id');
                }
                if ( stats.withRelationIds.col.filter(x => x.id == source.id).length === 0){
                  stats.withRelationIds.col.push(source);
                } else {
                  console.log('重复id');
                }

                if (existingRelationMatrix[key] == null) {
                  existingRelationMatrix[key] = [];
                }
                existingRelationMatrix[key].push({ stereotype, key: x.id });
              }
            }
          }

        } else {
          console.log(x.model, '没有getTargets方法??');
        }
      });
    };
    let treeRec = x => {
      //// relationGroup
      if (x.getTypeName() === 'Relations' ) {
        relationResursive(x);
      } else {
        x.children.forEach(y => {
          treeRec(y);
        });
      }
    };
    [app.sysmlModel].forEach(x => {
      treeRec(x);
    });
    console.log(existingRelationMatrix, 'existingRelationMatrix');
    return { existingRelationMatrix, legend, stats };
  },
  updateRelation(rowList, colList, filterCondition, tableData ){
    let { existingRelationMatrix, legend } = this.getExistingRelation(filterCondition);
    const l1 = rowList.length;
    const l2 = colList.length;
     
    for (let index = 0; index < l1; index++) {
      for (let index1 = 0; index1 < l2; index1++) {
        let relationKeyOut = colList[index1].id + '__' + rowList[index].id;
        let relationKeyIn = rowList[index].id + '__' + colList[index1].id;
        let relationArrayIn = existingRelationMatrix[relationKeyIn];
        let relationArrayOut = existingRelationMatrix[relationKeyOut];
        //// console.log({ relationKeyOut, relationIn });

        //// console.log(relationKeyIn, colIn['model'].name, rowOut['model'].name);
        let existingRelationIcon = null;
        //// 展示存在的关系数
        let existingRelationNumber = 0;
        if (relationArrayIn && tableData[index + '__' + index1].relationIn.length > 0) {
          existingRelationNumber =
            existingRelationNumber + relationArrayIn.length;
          if (existingRelationNumber == 1){
            existingRelationIcon = 'statics/images/sysml/' + relationArrayIn[0].stereotype + '.svg';
          } else {
            existingRelationIcon = 'statics/icons/table/directedin.svg';
          }

        }
        if (relationArrayOut && tableData[index + '__' + index1].relationOut.length > 0) {
          existingRelationNumber =
            existingRelationNumber + relationArrayOut.length;
          if (existingRelationNumber == 1){
            existingRelationIcon = 'statics/images/sysml/' + relationArrayOut[0].stereotype + '2.svg';
          } else {
            existingRelationIcon = 'statics/icons/table/directedout.svg';
          }

        }
        if (relationArrayIn && relationArrayOut) {
          existingRelationIcon = 'statics/icons/table/directedAll.svg';
        }

        if (existingRelationNumber < 2)existingRelationNumber = null;

        tableData[index + '__' + index1].existingRelationIcon = existingRelationIcon;
        tableData[index + '__' + index1].existingRelationNumber = existingRelationNumber;
        
      }
    }
    return  { tableData, legend };
  },
  //// 优化方法 =>将易变化部分和不变部分拆分，分别计算后得到这个matrix，或者UI上分步展示
  getRelationMatrix(rowList, colList, filterCondition) {
    //// dependencyCriteria dicrection
    //// 线类型过滤 方向过滤
    console.time('tree');
  
    console.timeEnd('tongji');

    //// todo 下面的getExistingRelation可以传进来 避免二次计算
    let { existingRelationMatrix, legend } = this.getExistingRelation(filterCondition);
    console.timeEnd('tree');
    //// 非空矩阵；空矩阵；行为空矩阵；列为空矩阵
    //// console.log({ rowList, colList }, '---getRelationMatrix');
    //// 写下草稿代码 然后在console中运行 验证通过后 再返回至此
    let relations = filterCondition.dependencyCriteria.filter(x => x.isVisible).map(x => x.icon);
    let tableData = {};
    //// 按照递归顺序展开  行 =>列  与tablevalue格式对接
    let connectConfig = app.activeProject.configManager.getConnectConfig();
    const l1 = rowList.length;
    const l2 = colList.length;
    for (let index = 0; index < l1; index++) {
      //// app.activeProject.configManager.getConnectConfig()[modelName].outgoing
      //// console.log(rowList[index].getTypeName(), 'typeName');
      let rowLoop = connectConfig[rowList[index].typeName];
      const rowIn = rowLoop?.incoming || [];//// rowList[index].incoming;
      const rowOut = rowLoop?.outgoing || [];//// rowList[index].outGoing;
      for (let index1 = 0; index1 < l2; index1++) {
        let colLoop = connectConfig[colList[index1].typeName];
        const colIn = colLoop?.outgoing || [];//// colList[index1].outGoing;
        const colOut = colLoop?.incoming || [];//// colList[index1].incoming;
        //// console.log({ colIn, rowIn });
        //// 什么情况能创建？？ colin与row out 重合的部分
        let relationIn = colIn.filter(v => relations.includes(v) && rowOut.includes(v));
        let relationOut = colOut.filter(v => relations.includes(v) && rowIn.includes(v));
        if (filterCondition.dicrection == 'rowToCol') {
          //// console.log('单向过滤:rowToCol');
          relationOut = [];
        }
        if (filterCondition.dicrection == 'colToRow') {
          //// console.log('单向过滤:colToRow');
          relationIn = [];
        }

        if (filterCondition.dicrection == 'both') {
          //// console.log('全部方向');
        }

        //// console.log(relationIn, relationOut, ' relationIn,relationOut');

        let disabled = relationIn.length == 0 && relationOut.length == 0;
        //// tableData[index + '__' + index1] = { disabled: disabled, relationIn: relationIn, relationOut: relationOut, from: colIn['model'], to: colOut['model'] };
        //// 稀疏矩阵已有关系展现
        let relationKeyOut = colList[index1].id + '__' + rowList[index].id;
        let relationKeyIn = rowList[index].id + '__' + colList[index1].id;
        let relationArrayIn = existingRelationMatrix[relationKeyIn];
        let relationArrayOut = existingRelationMatrix[relationKeyOut];
        //// console.log({ relationKeyOut, relationIn });

        //// console.log(relationKeyIn, colIn['model'].name, rowOut['model'].name);
        let existingRelationIcon = null;
        //// 展示存在的关系数
        let existingRelationNumber = 0;
        if (relationArrayIn && relationIn.length > 0) {
          existingRelationNumber =
            existingRelationNumber + relationArrayIn.length;
          if (existingRelationNumber == 1){
            existingRelationIcon = 'statics/images/sysml/' + relationArrayIn[0].stereotype + '.svg';
          } else {
            existingRelationIcon = 'statics/icons/table/directedin.svg';
          }

        }
        if (relationArrayOut && relationOut.length > 0) {
          existingRelationNumber =
            existingRelationNumber + relationArrayOut.length;
          if (existingRelationNumber == 1){
            existingRelationIcon = 'statics/images/sysml/' + relationArrayOut[0].stereotype + '2.svg';
          } else {
            existingRelationIcon = 'statics/icons/table/directedout.svg';
          }

        }
        if (relationArrayIn && relationArrayOut) {
          existingRelationIcon = 'statics/icons/table/directedAll.svg';
        }

        if (existingRelationNumber < 2)existingRelationNumber = null;
        let disabledCss = disabled ? 'treeCellDisable' : 'treeCellEnable';

        tableData[index + '__' + index1] = {
          disabled: disabled,
          disabledCss: disabledCss,
          relationIn: relationIn,
          relationOut: relationOut,
          existingRelationIcon: existingRelationIcon,
          existingRelationNumber: existingRelationNumber,
          keyX: colList[index1].id,
          keyY: rowList[index].id
        };
      }
    }
    //// console.log({ tableData, relations });

    return { tableData, legend };
  },
  isProfile(obj){
    if (obj.status === GraphNodeStatus.FROM_PROFILE) return true;
    return ['UML Standard Profile', 'SysML', 'M Design Profile'].includes(obj.title);

  },
  buildMatrixTypeList(){
 
    const typeNameConfig = app.activeProject.configManager.getTypeNameConfig();
    
    let elementArray = Object.values(typeNameConfig).sort((a:any, b:any) => {
      return a.cnName.localeCompare(b.cnName);
    }).filter((x:any, index) => x.type !== "diagram" ).map((x:any, index) => { return   {
      title: x.cnName,
      key: '0-' + index,
      value: x.typeName,
      icon: (app.configManager.getTypeNameConfigItem(x.typeName))?.icon,
      scopedSlots: {
        title: "default"
      }
    }; }
    );

    const treeDataMatrix = [
      {
        title: '全部元素',
        key: '0',
        value: 'Element',
        icon: "statics/images/sysml/CentralBufferNode.svg",
        disabled: false,
        checkbox: true,
        scopedSlots: {
          title: "default"
        },
        children: elementArray
      }
    ];
    return treeDataMatrix;
  },
};
